package com.yy.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yy.dto.DishDto;
import com.yy.entity.*;
import com.yy.mapper.CategoryMapper;
import com.yy.mapper.DishMapper;
import com.yy.service.*;
import com.yy.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * create by KongFuning on 2022/7/31
 */
@Service
@Slf4j
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {

    @Autowired
    private DishFlavorService dishFlavorService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private SetmealDishService setmealDishService;

    @Autowired
    private SetmealService setmealService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /*
     * 分页
     * */
    @Override
    public R<Page> pageDish(Integer page, Integer pageSize, String name) {
        Page<Dish> pageDish = new Page<>(page,pageSize);
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Dish::getIsDeleted,0);
        queryWrapper.like(StrUtil.isNotEmpty(name),Dish::getName,name);
        queryWrapper.orderByDesc(Dish::getUpdateTime);
        page(pageDish,queryWrapper);
        // -----------------------------------------------------------------
        Page<DishDto> pageDishDto = new Page<>(page,pageSize);
        // 将pageDish对象拷贝到pageDishDto中
        BeanUtil.copyProperties(pageDish,pageDishDto,"records");
        // 取出pageDish中的records
        List<Dish> dishList = pageDish.getRecords();
        // 对每一个Dish进行处理，转化成DishDto对象，并给分类名称赋值
        List<DishDto> dishDtoList = dishList.stream().map((item) ->{
            DishDto dishDto = new DishDto();
            BeanUtil.copyProperties(item,dishDto);
            // 查询出每个菜品分类id对应的分类名称
            String categoryName = categoryService.getById(item.getCategoryId()).getName();
            dishDto.setCategoryName(categoryName);
            // 格式化时间 去除T  2022-08-02T13:05:51
            return dishDto;
        }).collect(Collectors.toList());
        pageDishDto.setRecords(dishDtoList);
        return R.success(pageDishDto);
    }

    /*
     * 新增菜品 同时保存对应的口味数据
     * */
    @Override
    @Transactional
    public R saveWithFlavor(DishDto dishDto) {
        // 保存菜品的基本信息到菜品表dish
        save(dishDto);

        // 菜品id
        String dishId = dishDto.getId();

        // 菜品口味
        List<DishFlavor> flavors = dishDto.getFlavors();
        // 给每一种口味都设置上菜品id
        flavors = flavors.stream().map((item)->{
           item.setDishId(dishId);
           return item;
        }).collect(Collectors.toList());

        // 保存菜品的口味数据到菜品口味表 dish_flavor
        dishFlavorService.saveBatch(flavors);

        // 清理redis缓存
        stringRedisTemplate.delete("dish:categoryId:" + dishDto.getCategoryId());
        return R.success("新增菜品成功！");
    }

    /*
     * 修改菜品 回显数据
     * */
    @Override
    public R toUpdateWithFlavor(String id) {
        // 根据id查询Dish
        Dish dish = getById(id);
        // 将dish对象拷贝为dishDto
        DishDto dishDto = new DishDto();
        BeanUtil.copyProperties(dish,dishDto);
        // 根据dishId查询出对应的口味 dish_flavor
        List<DishFlavor> list = dishFlavorService.query().eq("dish_id", id).list();
        // 给dishDto设置上
        dishDto.setFlavors(list);
        return R.success(dishDto);
    }

    /*
     * 修改菜品 口味
     * */
    @Override
    @Transactional
    public R updateWithFlavor(DishDto dishDto) {
        // 更新菜品的基本信息
        updateById(dishDto);

        // 清理当前菜品对应的口味数据 —— dish_flavor表的delete 操作
        LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DishFlavor::getDishId,dishDto.getId());
        dishFlavorService.remove(queryWrapper);

        // 添加当前提交过来的口味数据 —— dish_flavor表的insert 操作
        List<DishFlavor> flavors = dishDto.getFlavors();
        flavors = flavors.stream().map((item)->{
            item.setDishId(dishDto.getId());
            return item;
        }).collect(Collectors.toList());
        dishFlavorService.saveBatch(flavors);

        // 清理redis缓存
        stringRedisTemplate.delete("dish:categoryId:" + dishDto.getCategoryId());
        return R.success("更新菜品成功！");
    }

    /*
     * 添加套餐 菜品列表回显
     * */
    // 加入Redis缓存
    @Override
    public R getDishList(DishDto dishDto) {
        List<DishDto> dishDtoList = new ArrayList<>();
        String categoryId = dishDto.getCategoryId();
        // 1、先从Redis缓存中查询该分类下的数据
        String dishesJson = stringRedisTemplate.opsForValue().get("dish:categoryId:" + categoryId);
        if(StrUtil.isNotBlank(dishesJson)){
            // 2、如果缓存中存在，则直接返回
            dishDtoList = JSONUtil.toList(dishesJson, DishDto.class);
            return R.success(dishDtoList);
        }
        // 判断命中的是否是空值
        if(dishesJson != null){
            // 返回错误信息
            return R.error("无菜品数据！");
        }
        // 3、如果缓存中不存在，则查询数据库返回数据，并写入缓存
        // 查询出对应分类下所有的菜品 基础信息
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(categoryId != null,Dish::getCategoryId,categoryId);
        queryWrapper.eq(Dish::getStatus,1);
        queryWrapper.eq(Dish::getIsDeleted,0);
        queryWrapper.orderByDesc(Dish::getUpdateTime);
        List<Dish> list = list(queryWrapper);
        // 如果数据库也没有，则返回一个空值 【缓存空值解决缓存穿透】
        if(list.isEmpty()){
            stringRedisTemplate.opsForValue().set("dish:categoryId:" + categoryId,"",2L,TimeUnit.MINUTES);
            return R.error("无菜品数据！");
        }
        // 转化成dishDto
        dishDtoList = list.stream().map((item)->{
            DishDto dd = new DishDto();
            // 将Dish拷贝到DishDto
            BeanUtil.copyProperties(item,dd);
            // 查询出菜品对应的口味list
            LambdaQueryWrapper<DishFlavor> qw = new LambdaQueryWrapper<>();
            qw.eq(DishFlavor::getDishId,item.getId());
            List<DishFlavor> dishFlavors = dishFlavorService.list(qw);
            dd.setFlavors(dishFlavors);
            // 根据分类id查询分类名
            String categoryName = categoryService.getById(item.getCategoryId()).getName();
            dd.setCategoryName(categoryName);
            return dd;
        }).collect(Collectors.toList());

        // 写入缓存
        stringRedisTemplate.opsForValue().set("dish:categoryId:" + categoryId,JSONUtil.toJsonStr(dishDtoList),60L, TimeUnit.MINUTES);
        return R.success(dishDtoList);
    }

    /*
     * 停售  起售
     * */
    @Override
    public R isSale(Integer status,String ids) {
        Dish dish = new Dish();
        dish.setStatus(status);
        dish.setId(ids);
        updateById(dish);
        return R.success("菜品状态更改成功！");
    }

    /*
     * 删除菜品
     * */
    @Override
    public R deleteDish(String ids) {
        // 判断该菜品是否关联了套餐
        LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StrUtil.isNotEmpty(ids),SetmealDish::getDishId, ids);
        List<SetmealDish> setmealList = setmealDishService.list(queryWrapper);
        if(!setmealList.isEmpty()){
            // 关联了套餐，无法删除
            // 查询关联套餐的套餐名称
            List<String> setmealName = new ArrayList<>();
            for (SetmealDish setmealDish : setmealList) {
                log.info("setmealList:{}", setmealDish.getSetmealId());
                setmealName.add(setmealService.getById(setmealDish.getSetmealId()).getName());
            }
            return R.error("该菜品关联了" + setmealName + ",无法删除！");
        }
        // 没有关联套餐，删除菜品
        // 逻辑删除，其实是将isDeleted更新为 1
        Dish dish = getById(ids);
        dish.setIsDeleted(1);
        updateById(dish);
        // 清理redis缓存
        stringRedisTemplate.delete("dish:categoryId:" + dish.getCategoryId());

        return R.success("删除菜品成功！");
    }

}
